package com.rolerealm.service.impl;

import com.rolerealm.common.constant.ErrorCode;
import com.rolerealm.common.exception.BusinessException;
import com.rolerealm.dao.SkillMapper;
import com.rolerealm.domain.entity.SkillEntity;
import com.rolerealm.domain.enums.SkillType;
import com.rolerealm.domain.dto.SkillDTOs.SkillExecuteRequest;
import com.rolerealm.domain.dto.SkillDTOs.SkillExecuteResponse;
import com.rolerealm.domain.vo.SkillVO;
import com.rolerealm.service.SkillService;
import com.rolerealm.service.LLMService;
import com.rolerealm.service.ModelRoutingService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 技能服务实现类
 * 
 * @author RoleRealm Team
 * @version 1.0.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SkillServiceImpl implements SkillService {

    private final SkillMapper skillMapper;
    private final ModelRoutingService modelRoutingService;
    private final LLMService llmService;
    private final java.util.List<com.rolerealm.service.strategy.SkillStrategy> strategies;

    @Override
    public List<SkillVO> getAllSkills() {
        log.debug("获取所有技能列表");
        
        List<SkillEntity> skills = skillMapper.selectList(null);
        
        return skills.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<SkillVO> getSkillsByType(String skillType) {
        log.debug("根据技能类型获取技能列表，技能类型：{}", skillType);
        
        List<SkillEntity> skills = skillMapper.selectBySkillType(skillType);
        
        return skills.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public SkillVO getSkillByCode(String skillCode) {
        log.debug("根据技能代码获取技能详情，技能代码：{}", skillCode);
        
        SkillEntity skill = skillMapper.selectBySkillCode(skillCode);
        if (skill == null) {
            return null;
        }
        
        return convertToVO(skill);
    }

    @Override
    public List<SkillVO> getEnabledSkills() {
        log.debug("获取启用的技能列表");
        
        List<SkillEntity> skills = skillMapper.selectEnabledSkills();
        
        return skills.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<SkillVO> getSkillsByTag(String tag) {
        log.debug("根据标签获取技能列表，标签：{}", tag);
        
        List<SkillEntity> skills = skillMapper.selectByTag(tag);
        
        return skills.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    /**
     * 转换为技能VO
     */
    private SkillVO convertToVO(SkillEntity entity) {
        SkillVO vo = new SkillVO();
        BeanUtils.copyProperties(entity, vo);
        
        // 解析标签字符串为列表
        if (StringUtils.hasText(entity.getTags())) {
            vo.setTags(Arrays.asList(entity.getTags().split(",")));
        } else {
            vo.setTags(Collections.emptyList());
        }
        
        return vo;
    }

    @Override
    public SkillExecuteResponse execute(String skillType, SkillExecuteRequest request) {
        if (!SkillType.isValid(skillType)) {
            throw new BusinessException(ErrorCode.SKILL_NOT_FOUND);
        }
        if (request == null || request.getCharacterId() == null) {
            throw new BusinessException(ErrorCode.PARAM_MISSING);
        }

        String languageCode = "zh"; // 简化：可依据角色或输入检测
        String model = modelRoutingService.routeModel(languageCode);

        String prompt = selectStrategyAndBuildPrompt(skillType, request.getInput());
        String content;
        try {
            // 如果路由返回 "wenxin"，则传模型标识给 LLMService；OpenAI 场景传入真实模型名
            content = llmService.infer(prompt, model);
        } catch (Exception e) {
            throw new BusinessException(ErrorCode.AI_INFERENCE_FAILED);
        }

        return SkillExecuteResponse.builder()
                .content(content)
                .build();
    }

    private String selectStrategyAndBuildPrompt(String skillType, String input) {
        com.rolerealm.service.strategy.SkillStrategy strategy = strategies.stream()
                .filter(s -> s.getType().name().equalsIgnoreCase(skillType))
                .findFirst()
                .orElseThrow(() -> new BusinessException(ErrorCode.SKILL_NOT_AVAILABLE));
        strategy.validate(input);
        return strategy.buildPrompt(input);
    }
}
